﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using System.Threading;

namespace TcpUdpSocket
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void btnBuildTcpServer_Click(object sender, EventArgs e)
        {
            var t = new Thread(tcpServer);
            t.Start();
        }


        /**
         * Dns          域名解析 静态类 
         *      .GetHostAddresses(hostname)     返回主机名对应的地址  IPAddress[]
         *      .GetHostName()                  返回本地主机名
         *      .GetHostEntry(ip/host)          将主机名/ip解析成 IPHostEntry
         * 
         * 
         * IPHostEntry  dns主机名和它对应的别名,地址的组成的信息. 配合 Dns 使用
         *      .AddressList                    主机的 IPAddres[]
         *      .HostName                       主机的dns名称
         * 
         * 
         * IPAddress    ip 地址
         *      .Any                             表示本机任意地址
         *      .Loopback                        表示本机回环地址
         *      .IsLoopback(addr)                是否环回地址
         *      .Parse(addr)                     将字符串ip地址转换为 IPAddress 实例
         *      .TryParse(addr, out IPAddress)   如果成功返回 true
         *      .ToString()                      将ip地址转换字符串表示   
         * 
         * 
         * IPEndPoint    ip地址和端口组成的网络端点
         *      .Address                        端点的 IPAddress
         *      .Port                           端点的 端口号
         * 
         * TcpListenser     tcp服务端
         *      .Active             是否正在主动监听
         *      .Server             获取基础 Socket
         *      .LocalEndopint      获取基础 EndPoint
         * 
         * 
         *       new TcpListenser(IPAddress.Any, 3389); 创建实例
         *      .Start()            开始监听端口
         *      .Close()            关闭监听, 不会关闭已接受的连接
         *      .AcceptSocket()     从传入队列提取连接请求
         *      .AcceptTcpClient()  从传入队列提取连接请求 返回 TcpClient
         *      .Pending()          是否有挂起的请求
         * 
         * TcpClient
         *      .Active             是否已经建立连接
         *      .Client             基础socket
         *      .Connected          基础socket是否已经连接到远程主机
         * 
         *      .GetStream()        获取 NetworkSteam 使用 Write, Read 发送接收数据, 
         *      .Close()            释放TcpClient关联资源
         *      .Connect(IPEndPoint)连接到远程服务器
         *  
         * NetWorkStream
         *      .CanRead            是否支持 read 方法读取数据
         *      .DataAvailable      stream 上是否有可以读的数据, 必须先调用 Read().
         *      
         *      
         */

        private void tcpServer()
        {
            Debug.WriteLine(string.Format("log: {0}", "启动服务进程 7730"));
            var server = new TcpListener(IPAddress.Any, 7730);
            server.Start();
            Debug.WriteLine(string.Format("log: {0}", "获取客户端连接, 会阻塞线程"));
            var client = server.AcceptTcpClient();
            Debug.WriteLine(string.Format("log: {0}", "已经获取到客户端连接"));
            var netStream = client.GetStream();
            var sr = new StreamReader(netStream);
            var sw = new StreamWriter(netStream);

            while (netStream.CanRead)
            {
                do
                {
                    var s = sr.ReadLine();
                    Debug.WriteLine(string.Format("s <- c: {0}", s));
                    if (s == "ping")
                    {
                        sw.WriteLine("pong");
                    }
                    else
                    {
                        sw.WriteLine(s);
                    }
                    sw.Flush();
                }
                while (netStream.DataAvailable);

                Thread.Sleep(1000);
            }
            Debug.WriteLine(string.Format("log: {0}", "进程 7730 已经结束"));
        }

        private void btnBuildTcpClient_Click(object sender, EventArgs e)
        {
            var t = new Thread(buildTcpClient);
            t.Start();
        }

        private void buildTcpClient()
        {
            var client = new TcpClient();
            client.Connect(new IPEndPoint(IPAddress.Loopback, 7730));

            int i = 0;
            var netStream = client.GetStream();
            var sr = new StreamReader(netStream);
            var sw = new StreamWriter(netStream);
            sw.WriteLine("ping");
            sw.Flush();

            while (netStream.CanRead)
            {
                i++;
                do
                {
                    var s = sr.ReadLine();
                    Debug.WriteLine(string.Format("s -> c: {0}", s));
                }
                while (netStream.DataAvailable);

                Thread.Sleep(2000);

                sw.WriteLine("Hi " + i.ToString());
                sw.Flush();
            }

        }

        private void btnBuildUdpServer_Click(object sender, EventArgs e)
        {
            var t = new Thread(udpServer);
            t.Start();
        }

        /**
         * UdpClient    udp 协议是无连接的
         *      new UdpClient(port)
         *      
         *      .Receive(ref ClientIPEndPoint)              获取远程主机发送的udp包, 会阻塞当前进程
         *      .Send(data, dateLenght, ServerIPEndPoint)   向远端主机发送数据
         * 
         */
        private void udpServer()
        {
            var server = new UdpClient(1330);
            var remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            while (true)
            {
                var data = server.Receive(ref remoteEndPoint);
                Debug.WriteLine(string.Format("s({0}) <- c({1}): {2}", Dns.GetHostName(), remoteEndPoint.ToString(),Encoding.Default.GetString(data)));
            }

        }

        private int i = 0;
        private void udpClient()
        {
            var server = new UdpClient();
            var remoteEndPoint = new IPEndPoint(IPAddress.Loopback, 1330);
            i++;
            var data = Encoding.Default.GetBytes("ping" + i.ToString());
            server.Send(data, data.Length, remoteEndPoint);
        }

        private void btnBuildUdpClient_Click(object sender, EventArgs e)
        {
            udpClient();
        }

    }
}
